// Copyright  2004-2008 Backplane Ltd.
//
// This file is part of Ubiquity formsPlayer
//
// Ubiquity formsPlayer is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at your
// option) any later version.
//
// Ubiquity formsPlayer is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License
// along with Ubiquity formsPlayer If not, see <http://www.gnu.org/licenses/>.
//	
//
//   Purpose: Implementation of CElementWithXBL.
//   $Id$

#include "stdafx.h"
#include "elementwithxbl.h"
#include <HTMLDOMTranslator.h>
#include "XFormsXFormsElement.h"
#include "UIImplRepository.h"

CElementWithXBL::CElementWithXBL(void)
{
}

CElementWithXBL::~CElementWithXBL(void)
{


}

STDMETHODIMP CElementWithXBL::Detach()
{
	HRESULT hr = __super::Detach();
	try
	{
		if(m_pEngine)
			m_pEngine->Detach();
		m_pEngine.Release();
	}
	catch(...)
	{
		::AtlTrace("\n!!formsPlayer.dll: Error detaching and releasing XBLEngine\n");
	}
	return hr;
}

HRESULT CElementWithXBL::changeUI() 
{
	HRESULT hr;
	if(m_pEngine)
	{
		m_pEngine->Detach();
		m_pEngine.Release();
	}

	if(!m_pEngine)
	{
		hr = getUI(&m_pEngine);
		if(m_pEngine)
		{
			CComQIPtr<IEngine2> pEngine2(m_pEngine);
			CComPtr<IHTMLElement> pEl;
			hr = GetMasterElement(&pEl);

			if(pEl)
			{
				CComQIPtr<IDispatchEx> pDispEx(pEl);
				hr = m_pEngine->Attach(pDispEx);
				//engine returns S_FALSE if no constructor is run.
				if(SUCCEEDED(hr))
					hr = S_OK;
			}
		}
	}
	return hr;
}

//At DocumentReady, fetch a UI Engine and attach it.
HRESULT CElementWithXBL::DocumentReady()
{
	HRESULT hr = __super::DocumentReady();
	hr = changeUI();
	return hr;
}

//<summary>
//	If specified, fetches a locally specified binding from an XML Data Island.
//</summary>
//<returns>
//	S_OK if successful<br />
//	S_FALSE if no xbl-binding was specified<br />
//	otehrwise, an error value.
//</returns>
HRESULT CElementWithXBL::GetLocallySpecifiedBinding(IEngine ** ppEngine)
{
	CComBSTR sId;
	HRESULT hr = GetLocallySpecifiedBindingId(sId);
	if(S_OK == hr && sId)
	{
		CUIImplRepository * pRepository = m_pXForms->GetUIImplRepository();
		if(pRepository)
		{
			CComPtr<IXMLDOMDocument> pXMLDocument;
//TEMPDISABLE
//			hr = m_pXForms->GetXMLElementById(sId,&pXMLDocument);
			if(pXMLDocument)
			{
				CComPtr<IXMLDOMNode> pNode;
				pXMLDocument->selectSingleNode(L"*",&pNode);
				if(pNode)
				{
hr = E_NOTIMPL;
					//					hr = pRepository->CreateUIImpl(pNode,ppEngine);	
					if(FAILED(hr))
					{
						CComBSTR bsXML;
						pNode->get_xml(&bsXML);
						::MessageBoxW(0,bsXML,0,0);
					}
				}	
			}
		}
		else
		{
			//hr = FP_E_NOREPOSITORY;
			//::SetupErrorInfo(hr);
		}
	}
	else
	{
		hr = S_FALSE;
	}
	return hr;
}

HRESULT CElementWithXBL::GetLocallySpecifiedBindingId(CComBSTR & bsId)
{
	HRESULT hr = S_FALSE;
	CComQIPtr<IHTMLElement> pMaster = GetControllingUnknown();
	if(pMaster)
	{
		CComVariant vtRetVal;
		CComBSTR bsXBLAttributeName(L"xbl-binding");
		hr = pMaster->getAttribute(bsXBLAttributeName,1,&vtRetVal);
		if(S_OK == hr && VT_BSTR == vtRetVal.vt)
		{
			bsId = vtRetVal.bstrVal;
		}
		else
		{
			hr = S_FALSE;
		}
	}
	return hr;
}

HRESULT CElementWithXBL::getUI(IEngine ** ppEngine)
{
	HRESULT hr = E_FAIL;
	
	//First see if it has an xbl-binding attribute 
	//	which can be used to retrieve a node from an 
	//	xml data island in the master document.
	hr = GetLocallySpecifiedBinding(ppEngine);
	if(S_FALSE == hr)
	{
	
		//Then use the standard transformation method.
		CComPtr<IXMLDOMNode> pNode;
		hr = getXML(&pNode);

		if(pNode) 
		{
			//get the xblEngine
			CUIImplRepository * pRepository = m_pXForms->GetUIImplRepository();
			
			try
			{
				hr = pRepository->GetUIImpl(pNode,ppEngine);
				if(!*ppEngine)
				{
					CComBSTR sTagsXML;
					pNode->get_xml(&sTagsXML);
					//ATLTRACE2("'formsplayer.dll': No UI handler loaded for %S\n",sTagsXML);
				}
			} 
			catch(...) 
			{
				CComPtr<IErrorInfo> pErr;
				::GetErrorInfo(0,&pErr);
				CComBSTR sDescription;
				if(pErr)
					pErr->GetDescription(&sDescription);
				CString s;
				CComBSTR sTagsXML;
				pNode->get_xml(&sTagsXML);
				s.Format("'formsplayer.dll': error %S in resolving UI for:\n %S\n",sDescription,sTagsXML);
				::MessageBox(0,s,0,0);
			}

		}
	}

	return hr;
}
